/*=+--+=#=+--     Unmanned Aerial System Management Software      --+=#=+--+=#*\
|          Copyright (C) 2011 Regents of the University of Colorado.           |
|                             All Rights Reserved.                             |

     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU General Public License version 2 as
     published by the Free Software Foundation.

     This program is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.

     You should have received a copy of the GNU General Public License
     along with this program.  If not, see <http://www.gnu.org/licenses/>.

            Jack Elston                       Cory Dixon                        
|           elstonj@colorado.edu              dixonc@colorado.edu              |
|                                                                              |
\*=+--+=#=+--                 --+=#=+--+=#=+--                    --+=#=+--+=#*/

#include "dmPage.h"
#include "myStripChart.h"
#include "vcConfig.h"

/*<---Extern Variables---->*/
extern GuiStruct  guiStr;
extern FifoMsg_t *fifo;

bool DMPage::create_page(Client *client, GtkBuilder *builder)
{	
	if( !client ) {
		cout << "DMPage::create_page -- invalid client " << endl;
		return false;
	}
	if( page ) {
		cout << "DMPage::update -- page has already been created" << endl;
		return true;
	}
	if( !builder ) {
		cout << "DMPage::update -- invalid xml builder" << endl;
		return false;
	}

	page_client = client;
	page        = GTK_WIDGET (gtk_builder_get_object(builder, "dm_page"));

	if( !page )
  {
		cout << "DMPage::create_page - did not find the page widget in the xml file" << endl;	
		page = NULL;
		return false;
	}

  for (int i=0; i<NUM_DEPLOY_MECHANISMS; i++) {
    char deploy_name[100];
    char dm_label_name[100];
    char evbox_name[100];

    sprintf(&deploy_name[0], "deploy_%d", i);
    sprintf(&dm_label_name[0], "dm_label%d", i);
    sprintf(&evbox_name[0], "evbox%d", i);

  
    deploy[i]     = GTK_WIDGET (gtk_builder_get_object(builder, deploy_name));
    labels[i]     = GTK_WIDGET (gtk_builder_get_object(builder, dm_label_name));
    evboxes[i]    = GTK_WIDGET (gtk_builder_get_object(builder, evbox_name));

    if ( !(deploy[i] && labels[i] && evboxes[i]) ) {
      cout << "DMPage::create_page - did not find the deploy/label/evbox widget(s) in the xml file" << endl;	
      page = NULL;
      return false;
    }

    g_signal_connect_after((GtkToggleButton*)deploy[i], "toggled", 
      G_CALLBACK(DMPage::send_deploy), this);
  }

	return true;
}

void DMPage::update()
{
  Mothership_t *ms;

	if( !page_client ) {
		cout << " - invalid page_client" << endl;
		return;
	}
	//-- See if the page has been initialized
	if( page == NULL ) {
		cout << "DMPage::update -- page has not been created" << endl;
		return;
	}

	// don't do work if we don't need too
	if( !GTK_WIDGET_VISIBLE( page ) ) {
		return;
	}

  ms = &(page_client->mothership);
  for (int i = 0; i < NUM_DEPLOY_MECHANISMS; i++) {
    //cout << ms->pegs[i].id << " status: " << ms->pegs[i].status << endl;
    gtk_label_set_text((GtkLabel*)labels[i], ms->pegs[i].id);
    ds[i] = ms->pegs[i].status;

    // update the status
    if (ms->pegs[i].status == DM_ERROR) {
      GdkColor red; gdk_color_parse ("red", &red);
      gtk_widget_modify_bg( evboxes[i], GTK_STATE_NORMAL, &red ); 
      gtk_toggle_button_set_active( (GtkToggleButton*)deploy[i], FALSE );
      gtk_widget_set_state( deploy[i], GTK_STATE_INSENSITIVE );
    }
    if (ms->pegs[i].status == DM_EMPTY) {
      GdkColor blue; gdk_color_parse ("blue", &blue);
      gtk_widget_modify_bg( evboxes[i], GTK_STATE_NORMAL, &blue ); 
      gtk_widget_set_sensitive( deploy[i], TRUE);
    }
    if (ms->pegs[i].status == DM_LOADED) {
      GdkColor green; gdk_color_parse ("green", &green);
      gtk_widget_modify_bg( evboxes[i], GTK_STATE_NORMAL, &green ); 
      gtk_widget_set_sensitive( deploy[i], TRUE );
    }
  }

	// redraw page
	gtk_widget_queue_draw(page);	
}

// use this function to indicate a command or ACK has been received
void DMPage::setCMD_RX(uint8_t cmd_id, int ack_nack)
{
	//cout << "DMPage::setCMD_RX - [" << (int)cmd_id << "]  ackNack=" << ack_nack << endl;
	if( page )
		gtk_widget_queue_draw(page);
}

//-----------------------------------------------------------
// button handlers -- we pass a WindowStruct pointer
void DMPage::send_deploy(GtkButton *button, gpointer data) {
  DMPage *dm = (DMPage *)data;
  if (!dm) return; // sanity check

  Client *me        = guiStr.shm_ptr->clients.getClient(0);
  fifo->src.s_addr = guiStr.shm_ptr->clients.getAddr(me, dm->page_client).s_addr;
  fifo->dest.s_addr = guiStr.shm_ptr->clients.getAddr(dm->page_client).s_addr;

  int *peg = (int*)CMD_DATAPTR(fifo->data);
  CMD_CMD(fifo->data)  = CMD_DEPLOY_PEG;
	CMD_NUM(fifo->data)  = sizeof(DMDeploy_t);
  *peg = dm->button_to_peg((GtkWidget*)button);

  if ( !((*peg >= 0) && (*peg < NUM_DEPLOY_MECHANISMS)) )
    return;
  dm->ds[*peg] = DM_EMPTY;
	
  CMD_CSUM(fifo->data) = 0;
	CMD_CSUM(fifo->data) = C_calcCheckSum((uint8_t*)fifo->data);
	fifo->size = CMD_SIZE(fifo->data);

	guiStr.vcgui->writeFifo(ThreadedPipe::INBOARD_TX);

  // we know sending this works!
  cout << "DMPage::deploy_button (" << *peg << ") pressed" << endl;
}

int DMPage::button_to_peg(GtkWidget *button) {
  
  // figure out which button 
  // case statements can't handle pointers
  for (int i=0; i<NUM_DEPLOY_MECHANISMS; i++)
    if (button == deploy[i])
      return i;

  cout << "unable determine send_deploy button source" << endl;
  return -1;
}
